<p>A user password should never be stored in clear-text, instead a hash should be produced from it using a secure algorithm:</p>
<ul>
  <li> not vulnerable to <code>brute force attacks</code>. </li>
  <li> not vulnerable to <code>collision attacks</code> (see rule s4790). </li>
  <li> and a salt should be added to the password to lower the risk of <code>rainbow table attacks</code> (see rule s2053). </li>
</ul>
<p>This rule raises an issue when a password is stored in clear-text or with a hash algorithm vulnerable to <code>bruce force attacks</code>. These
algorithms, like <code>md5</code> or <code>SHA-family</code> functions are fast to compute the hash and therefore brute force attacks are possible
(it’s easier to exhaust the entire space of all possible passwords) especially with hardware like GPU, FPGA or ASIC. Modern password hashing
algorithms such as <code>bcrypt</code>, <code>PBKDF2</code> or <code>argon2</code> are recommended.</p>
<h2>Noncompliant Code Example</h2>
<pre>
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
  auth.jdbcAuthentication()
    .dataSource(dataSource)
    .usersByUsernameQuery("SELECT * FROM users WHERE username = ?")
    .passwordEncoder(new StandardPasswordEncoder()); // Noncompliant

  // OR
  auth.jdbcAuthentication()
    .dataSource(dataSource)
    .usersByUsernameQuery("SELECT * FROM users WHERE username = ?"); // Noncompliant; default uses plain-text

  // OR
  auth.userDetailsService(...); // Noncompliant; default uses plain-text
  // OR
  auth.userDetailsService(...).passwordEncoder(new StandardPasswordEncoder()); // Noncompliant
}
</pre>
<h2>Compliant Solution</h2>
<pre>
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
  auth.jdbcAuthentication()
    .dataSource(dataSource)
    .usersByUsernameQuery("Select * from users where username=?")
    .passwordEncoder(new BCryptPasswordEncoder());

  // or
  auth.userDetailsService(null).passwordEncoder(new BCryptPasswordEncoder());
}
</pre>
<h2>See</h2>
<ul>
  <li> <a href="https://owasp.org/Top10/A02_2021-Cryptographic_Failures/">OWASP Top 10 2021 Category A2</a> - Cryptographic Failures </li>
  <li> <a href="https://owasp.org/Top10/A03_2021-Injection/">OWASP Top 10 2021 Category A4</a> - Insecure Design </li>
  <li> <a href="https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html">OWASP CheatSheet</a> - Password Storage Cheat Sheet
  </li>
  <li> <a href="https://owasp.org/www-project-top-ten/2017/A3_2017-Sensitive_Data_Exposure">OWASP Top 10 2017 Category A3</a> - Sensitive Data
  Exposure </li>
  <li> <a href="https://cwe.mitre.org/data/definitions/256.html">MITRE, CWE-256</a> - Plaintext Storage of a Password </li>
  <li> <a href="https://cwe.mitre.org/data/definitions/916.html">MITRE, CWE-916</a> - Use of Password Hash With Insufficient Computational Effort
  </li>
  <li> <a href="https://www.sans.org/top25-software-errors/#cat3">SANS Top 25</a> - Porous Defenses </li>
</ul>

